# -*- coding: utf-8 -*-
"""
风险控制模块 - 数据模型定义

本文件定义了测试DEMO中风险控制相关的所有数据模型，包括：

1. RiskIndicator - 风险指标模型
   - 定义各种风险评估指标
   - 包含指标名称、代码、描述和计算方法
   - 设置低、中、高风险阈值
   - 支持指标的激活/停用管理
   - 为风险评估提供标准化指标体系

2. RiskAlert - 风险预警模型
   - 管理投资组合的风险预警信息
   - 支持多级预警（低、中、高、极高风险）
   - 记录当前值与阈值的对比
   - 跟踪预警状态（激活、已解决、已忽略）
   - 支持预警的处理和解决流程

3. RiskAssessmentResult - 风险评估结果模型
   - 存储投资组合的风险评估结果
   - 包含总体风险评分和多维度风险指标
   - 计算VaR（风险价值）、最大回撤、夏普比率等
   - 提供相关性矩阵和风险分解分析
   - 生成个性化的风险管理建议

4. RiskLimit - 风险限额模型
   - 设置投资组合的各类风险限额
   - 支持持仓、集中度、VaR、回撤、杠杆等限额类型
   - 实时监控限额使用率和突破情况
   - 提供限额管理和预警功能
   - 确保投资组合在可控风险范围内运作

5. RiskMonitoringTask - 风险监控任务模型
   - 管理定时风险监控任务
   - 支持任务调度和状态跟踪
   - 记录任务执行结果和错误信息
   - 提供自动化风险监控能力
   - 确保风险控制的及时性和准确性

风险预警级别说明：
- 低风险: 风险指标在正常范围内
- 中风险: 风险指标接近预警阈值
- 高风险: 风险指标超过预警阈值
- 极高风险: 风险指标严重超标，需要立即处理

风险限额类型说明：
- 持仓限额: 控制单一资产的最大持仓比例
- 集中度限额: 限制投资组合的集中度风险
- VaR限额: 控制投资组合的最大可能损失
- 回撤限额: 限制投资组合的最大回撤幅度
- 杠杆限额: 控制投资组合的杠杆倍数

这些模型构成了完整的风险控制体系，为投资组合提供
全方位的风险监控、评估、预警和限额管理功能。

Author: zhaozeliang
Date: 2025-09-06
"""

from django.db import models
from django.utils import timezone
from users.models import User
from portfolios.models import Portfolio


class RiskIndicator(models.Model):
    """
    风险指标模型
    """
    name = models.CharField(max_length=100, verbose_name='指标名称')
    code = models.CharField(max_length=50, unique=True, verbose_name='指标代码')
    description = models.TextField(blank=True, null=True, verbose_name='指标描述')
    calculation_method = models.TextField(verbose_name='计算方法')
    threshold_low = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='低风险阈值')
    threshold_medium = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='中风险阈值')
    threshold_high = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='高风险阈值')
    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        db_table = 'risk_indicators'
        verbose_name = '风险指标'
        verbose_name_plural = '风险指标'
    
    def __str__(self):
        return f'{self.name} ({self.code})'


class RiskAlert(models.Model):
    """
    风险预警模型
    """
    ALERT_LEVELS = [
        ('low', '低风险'),
        ('medium', '中风险'),
        ('high', '高风险'),
        ('critical', '极高风险')
    ]
    
    ALERT_STATUS = [
        ('active', '激活'),
        ('resolved', '已解决'),
        ('ignored', '已忽略')
    ]
    
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, verbose_name='投资组合')
    indicator = models.ForeignKey(RiskIndicator, on_delete=models.CASCADE, verbose_name='风险指标')
    alert_level = models.CharField(max_length=20, choices=ALERT_LEVELS, verbose_name='预警级别')
    current_value = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='当前值')
    threshold_value = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='阈值')
    message = models.TextField(verbose_name='预警消息')
    status = models.CharField(max_length=20, choices=ALERT_STATUS, default='active', verbose_name='状态')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    resolved_at = models.DateTimeField(blank=True, null=True, verbose_name='解决时间')
    resolved_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='解决人')
    
    class Meta:
        db_table = 'risk_alerts'
        verbose_name = '风险预警'
        verbose_name_plural = '风险预警'
        ordering = ['-created_at']
    
    def __str__(self):
        return f'{self.portfolio.name} - {self.indicator.name} - {self.get_alert_level_display()}'


class RiskAssessmentResult(models.Model):
    """
    风险评估结果模型
    """
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, verbose_name='投资组合')
    assessment_date = models.DateTimeField(default=timezone.now, verbose_name='评估日期')
    overall_risk_score = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='总体风险评分')
    volatility = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='波动率')
    var_95 = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='95% VaR')
    var_99 = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='99% VaR')
    max_drawdown = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='最大回撤')
    sharpe_ratio = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='夏普比率')
    beta = models.DecimalField(max_digits=10, decimal_places=4, verbose_name='贝塔系数')
    correlation_matrix = models.JSONField(blank=True, null=True, verbose_name='相关性矩阵')
    risk_breakdown = models.JSONField(blank=True, null=True, verbose_name='风险分解')
    recommendations = models.TextField(blank=True, null=True, verbose_name='建议')
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        db_table = 'risk_assessment_results'
        verbose_name = '风险评估结果'
        verbose_name_plural = '风险评估结果'
        ordering = ['-assessment_date']
    
    def __str__(self):
        return f'{self.portfolio.name} - {self.assessment_date.strftime("%Y-%m-%d")}'


class RiskLimit(models.Model):
    """
    风险限额模型
    """
    LIMIT_TYPES = [
        ('position', '持仓限额'),
        ('concentration', '集中度限额'),
        ('var', 'VaR限额'),
        ('drawdown', '回撤限额'),
        ('leverage', '杠杆限额')
    ]
    
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, verbose_name='投资组合')
    limit_type = models.CharField(max_length=20, choices=LIMIT_TYPES, verbose_name='限额类型')
    limit_value = models.DecimalField(max_digits=15, decimal_places=4, verbose_name='限额值')
    current_value = models.DecimalField(max_digits=15, decimal_places=4, default=0, verbose_name='当前值')
    utilization_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0, verbose_name='使用率(%)')
    is_breached = models.BooleanField(default=False, verbose_name='是否突破')
    description = models.TextField(blank=True, null=True, verbose_name='描述')
    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        db_table = 'risk_limits'
        verbose_name = '风险限额'
        verbose_name_plural = '风险限额'
        unique_together = ['portfolio', 'limit_type']
    
    def __str__(self):
        return f'{self.portfolio.name} - {self.get_limit_type_display()}'
    
    def update_utilization(self):
        """更新使用率"""
        if self.limit_value > 0:
            self.utilization_rate = (self.current_value / self.limit_value) * 100
            self.is_breached = self.utilization_rate > 100
        else:
            self.utilization_rate = 0
            self.is_breached = False
        self.save()


class RiskMonitoringTask(models.Model):
    """
    风险监控任务模型
    """
    TASK_STATUS = [
        ('pending', '待执行'),
        ('running', '执行中'),
        ('completed', '已完成'),
        ('failed', '失败')
    ]
    
    name = models.CharField(max_length=100, verbose_name='任务名称')
    description = models.TextField(blank=True, null=True, verbose_name='任务描述')
    task_type = models.CharField(max_length=50, verbose_name='任务类型')
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, null=True, blank=True, verbose_name='投资组合')
    status = models.CharField(max_length=20, choices=TASK_STATUS, default='pending', verbose_name='状态')
    scheduled_time = models.DateTimeField(verbose_name='计划执行时间')
    started_at = models.DateTimeField(blank=True, null=True, verbose_name='开始时间')
    completed_at = models.DateTimeField(blank=True, null=True, verbose_name='完成时间')
    result_data = models.JSONField(blank=True, null=True, verbose_name='结果数据')
    error_message = models.TextField(blank=True, null=True, verbose_name='错误信息')
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        db_table = 'risk_monitoring_tasks'
        verbose_name = '风险监控任务'
        verbose_name_plural = '风险监控任务'
        ordering = ['-scheduled_time']
    
    def __str__(self):
        return f'{self.name} - {self.get_status_display()}'